/**
 *
 */
package com.ybkj.daijia.api;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ybkj.daijia.Setting;
import com.ybkj.daijia.serverUtils.SettingUtils;
import com.ybkj.daijia.api.member.alipay.config.AlipayConfig;
import com.ybkj.daijia.api.member.alipay.sign.MemberOrderSign;
import com.ybkj.daijia.api.member.alipay.sign.RSA;
import com.ybkj.daijia.api.member.alipay.util.AlipayNotify;
import com.ybkj.daijia.api.util.ErrorConstantV4;
import com.ybkj.daijia.api.util.ResultTransport;
import com.ybkj.daijia.api.weixin.tenpayv3.Configuration;
import com.ybkj.daijia.api.weixin.tenpayv3.GetWxOrderno;
import com.ybkj.daijia.api.weixin.tenpayv3.RequestHandler;
import com.ybkj.daijia.api.weixin.tenpayv3.Sha1Util;
import com.ybkj.daijia.api.weixin.tenpayv3.TenpayUtil;
import com.ybkj.daijia.common.Result;
import com.ybkj.daijia.config.RentApi;
import com.ybkj.daijia.server.mc.Enterprise;
import com.ybkj.daijia.server.mc.Passenger;
import com.ybkj.daijia.server.mc.PassengerAccount;
import com.ybkj.daijia.server.model.RentOrder;
import com.ybkj.daijia.server.service.MemberService;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Blazk.
 *
 */
@RestController("RentPayController")
@RequestMapping(value = "api/rentpay/")
public class RentPayController {

    @Autowired
    private SettingUtils settingUtils;
    @Autowired
    private MemberService memberService;
    @Autowired
    private RentApi rentApi;

    // 支付宝支付前的接口
    @RequestMapping(value = "zuchePrePay", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport alipayPrepay(
        HttpServletResponse response, HttpServletRequest request,
        Long orderGroupId, Double amount) {
        try {
            Setting setting = settingUtils.get();

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("PartnerID", setting.getAlipayPartnerID());
            map.put("SellerID", setting.getAlipaySellerID());
            map.put("PartnerPrivKey", setting.getAlipayPartnerPrivKey());
            map.put("PartnerPublicKey", AlipayConfig.ali_public_key);
            map.put("tradeNO", "zuche_prepay_" + orderGroupId);// 临时表订单Id或分组id
            map.put("productName", "租车支付");
            map.put("productDescription", "租车预先支付充值");
            map.put("amount", amount);
            map.put("notifyURL", setting.getWebUrl()
                + "/api/rentpay/alipay/notify");
            String content = MemberOrderSign.sign(map);
            String sign = RSA.sign(content, setting.getAlipayPartnerPrivKey(),
                "utf-8");
            sign = URLEncoder.encode(sign, "utf-8");
            String url = content + "&sign=\"" + sign + "\"&sign_type=\"RSA\"";

            Map<String, Object> data = new HashMap<String, Object>();
            data.put("url", url);

            ResultTransport instance = ResultTransport
                .getErrorBy(ErrorConstantV4.SUCCESS);
            instance.setData(data);
            return instance;
        } catch (Exception e) {
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }
    }

    // 支付宝支付后的接口
    @RequestMapping(value = "alipay/notify")
    public synchronized @ResponseBody
    String alipayNotify(
        HttpServletResponse response, HttpServletRequest request) {
        try {
            Setting setting = settingUtils.get();
            // 获取支付宝POST过来反馈信息
            Map<String, String> params = new HashMap<String, String>();
            Map requestParams = request.getParameterMap();

            for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                String name = (String) iter.next();
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
                }
                // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
                // valueStr = new String(valueStr.getBytes("ISO-8859-1"),
                // "gbk");
                params.put(name, valueStr);
            }
            // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
            // 商户订单号
            String out_trade_no = new String(
                request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
            // 支付宝交易号
            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),
                "UTF-8");
            // 交易状态
            String trade_status = new String(
                request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
            // 交易状态
            BigDecimal total_amount = new BigDecimal(request.getParameter("total_fee"));

            // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            if (AlipayNotify.verify(params, setting)) {// 验证成功
                if (trade_status.equals("TRADE_FINISHED")) {
                    // 创建财务信息
                    Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                    RentOrder order = selectRentOrder(orderId);
                    if (null != order) {
                        // 获取客户信息
                        Passenger passenger = memberService
                            .findOnePassenger(order.getPassengerId());
                        if (null != passenger) {
                            Result<PassengerAccount> result = new Result<PassengerAccount>();
                            if (passenger.getType().equals(
                                Passenger.TYPE_PASSENGER)) {
                                // 更新个人客户信息和添加账户信息
                                result = memberService
                                    .money(passenger,
                                        null,
                                        total_amount.negate(),
                                        "支付宝支付" + total_amount + "元", "系统",
                                        PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                        order.getId(),
                                        order.getOrderNo(), 3, null,
                                        false, true);
                            }
                            if (passenger.getType().equals(
                                Passenger.TYPE_ENTERPRISE)) {
                                Enterprise enterprise = memberService
                                    .findOneEnterprise(passenger
                                        .getEnterprise_id());
                                result = memberService
                                    .moneyEnterprise(
                                        enterprise,
                                        total_amount.negate(),
                                        "支付宝支付" + total_amount + "元",
                                        "系统",
                                        PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                        order.getId(),
                                        order.getOrderNo(), 3, null,
                                        false, true);
                            }
                            if (result.isSuccess()) {
                                this.payed(order.getId(), total_amount);
                                return "success";
                            } else {
                                return "fail";
                            }
                        }
                    }
                } else if (trade_status.equals("TRADE_SUCCESS")) {
                    // 创建财务信息
                    Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                    RentOrder order = selectRentOrder(orderId);
                    if (null != order) {
                        // 获取客户信息
                        Passenger passenger = memberService
                            .findOnePassenger(order.getPassengerId());
                        if (null != passenger) {
                            Result<PassengerAccount> result = new Result<PassengerAccount>();
                            if (passenger.getType().equals(
                                Passenger.TYPE_PASSENGER)) {
                                // 更新个人客户信息和添加账户信息
                                result = memberService
                                    .money(passenger,
                                        null,
                                        total_amount.negate(),
                                        "结算使用支付宝支付" + total_amount
                                            + "元",
                                        "系统",
                                        PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                        order.getId(),
                                        order.getOrderNo(), 3, null,
                                        false, true);
                            }
                            if (passenger.getType().equals(
                                Passenger.TYPE_ENTERPRISE)) {
                                Enterprise enterprise = memberService
                                    .findOneEnterprise(passenger
                                        .getEnterprise_id());
                                result = memberService
                                    .moneyEnterprise(
                                        enterprise,
                                        total_amount.negate(),
                                        "结算使用支付宝支付" + total_amount
                                            + "元",
                                        "系统",
                                        PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                        order.getId(),
                                        order.getOrderNo(), 3, null,
                                        false, true);
                            }
                            if (result.isSuccess()) {
                                this.payed(order.getId(), total_amount);
                                return "success";
                            } else {
                                return "fail";
                            }
                        }
                    }
                }
                return "fail";
            } else {
                return "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "fail";
    }

    // 微信支付前接口api/rentpay/prepay
    @RequestMapping(value = "wx/prepay", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport genpackage(
        HttpServletResponse response, HttpServletRequest request,
        Long orderGroupId, BigDecimal amount) {

        Setting setting = settingUtils.get();
        String createOrderURL = Configuration.createOrderURL;

        // 商户相关资料
        String appid = setting.getWxAppID();
        String appsecret = setting.getWxAppSecret();
        String partner = setting.getWxPartnerID();
        String partnerkey = setting.getWxPartnerKey();

        // 获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder
        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(6) + "";
        // 10位序列号,可以自行调整。
        String strReq = strTime + strRandom;
        // 商户号
        String mch_id = partner;
        // 随机数
        String nonce_str = strReq;
        // 商品描述
        String body = "租车付费";
        // 商户订单号
        String out_trade_no = "zuche_prepay_" + orderGroupId;
        // 总金额以分为单位，不带小数点
        String total_fee = String.valueOf(amount.multiply(new BigDecimal(100))
            .intValue());
        // 订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr();

        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = setting.getWebUrl() + "/api/rentpay/wx/notify";

        String trade_type = "APP";

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);
        // 这里写的金额为1 分到时修改
        // packageParams.put("total_fee", "1");
        packageParams.put("total_fee", total_fee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);

        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>"
            + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
            + "</nonce_str>" + "<sign>" + sign + "</sign>"
            + "<body><![CDATA[" + body + "]]></body>" + "<out_trade_no>"
            + out_trade_no + "</out_trade_no>" + "<total_fee>" + total_fee
            + "</total_fee>" + "<spbill_create_ip>" + spbill_create_ip
            + "</spbill_create_ip>" + "<notify_url>" + notify_url
            + "</notify_url>" + "<trade_type>" + trade_type
            + "</trade_type>" + "</xml>";

        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
            if (prepay_id.equals("")) {
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appid", appid);
        finalpackage.put("partnerid", partner);
        finalpackage.put("prepayid", prepay_id);
        finalpackage.put("package", "Sign=WXPay");
        finalpackage.put("noncestr", nonce_str);
        finalpackage.put("timestamp", timestamp);
        String finalsign = reqHandler.createSign(finalpackage);
        finalpackage.put("sign", finalsign);
        finalpackage.put("success", Boolean.TRUE.toString());
        ResultTransport instance = ResultTransport
            .getErrorBy(ErrorConstantV4.SUCCESS);
        instance.setData(finalpackage);
        return instance;
    }

    // 微信支付后接口
    @RequestMapping(value = "wx/notify", method = RequestMethod.POST)
    public synchronized @ResponseBody
    String wxNotify(
        HttpServletResponse response, HttpServletRequest request)
        throws Exception {

        String out_trade_no = "";
        BigDecimal total_fee = BigDecimal.ZERO;
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(
                request.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            String strxml = sb.toString();
            InputStream in = new ByteArrayInputStream(strxml.getBytes());
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(in);
            Element root = doc.getRootElement();
            List list = root.getChildren();
            Iterator it = list.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String k = e.getName();
                if (k.equals("out_trade_no")) {
                    out_trade_no = e.getText();
                    if (StringUtils.isNotBlank(out_trade_no)) {
                        String[] split = out_trade_no.split("_");
                        out_trade_no = split[0] + "_" + split[1] + "_"
                            + split[2];
                    }
                }
                if (k.equals("total_fee")) {
                    total_fee = new BigDecimal(e.getText())
                        .divide(new BigDecimal(100));
                }
            }
            try {
                // 关闭流
                if (null != in) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (StringUtils.isBlank(out_trade_no)) {
                return "FAIL";
            }
            // 创建财务信息
            Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
            RentOrder order = selectRentOrder(orderId);
            if (null != order) {
                // 获取客户信息
                Passenger passenger = memberService.findOnePassenger(order
                    .getPassengerId());
                if (null != passenger) {
                    Result<PassengerAccount> result = new Result<PassengerAccount>();
                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        // 更新个人客户信息和添加账户信息
                        result = memberService.money(passenger, null, total_fee.negate(),
                            "结算使用微信支付" + total_fee + "元", "系统",
                            PassengerAccount.PayType.PAYTYPE_WEIXIN,
                            order.getId(), order.getOrderNo(), 3, null,
                            false, true);
                    }
                    if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                        Enterprise enterprise = memberService
                            .findOneEnterprise(passenger.getEnterprise_id());
                        result = memberService.moneyEnterprise(enterprise,
                            total_fee.negate(), "结算使用微信支付" + total_fee + "元", "系统",
                            PassengerAccount.PayType.PAYTYPE_WEIXIN,
                            order.getId(), order.getOrderNo(), 3, null,
                            false, true);
                    }
                    if (result.isSuccess()) {
                        this.payed(order.getId(), total_fee);
                        return "SUCCESS";
                    } else {
                        return "FAIL";
                    }
                }
            }
            return "FAIL";
        } catch (Exception e) {
            e.printStackTrace();
            return "FAIL";
        }
    }

    @RequestMapping(value = "prePay", method = RequestMethod.POST)
    public Map<String, Object> prePay(@RequestParam("id") Long id,
        @RequestParam("payed") Double payed, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<String, Object>();
        // 获取订单信息
        RentOrder order = selectRentOrder(id);
        if (null != order) {
            // 获取客户信息
            Passenger passenger = memberService.findOnePassenger(order
                .getPassengerId());
            if (null != passenger) {// 余额支付
                // 获取客户余额
                Double cash = passenger.getDrawMoney()
                    .add(passenger.getNodrawMoney()).doubleValue();
                if (payed > cash) {// 客户余额不足
                    map.put("message", "余额不足");
                    map.put("success", false);
                    map.put("code", -1);
                } else {// 客户余额充足，余额扣除
                    Result<PassengerAccount> result = new Result<PassengerAccount>();
                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        // 更新个人客户信息和添加账户信息
                        result = memberService.money(passenger, null, new BigDecimal(
                                payed).negate(), "结算使用余额支付" + payed + "元", "系统",
                            PassengerAccount.PayType.PAYTYPE_BALANCE, order
                                .getId(), order.getOrderNo(), 3, null,
                            true, true);
                    }
                    if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                        Enterprise enterprise = memberService
                            .findOneEnterprise(passenger.getEnterprise_id());
                        result = memberService.moneyEnterprise(enterprise,
                            new BigDecimal(payed).negate(),
                            "结算使用余额支付" + payed + "元", "系统",
                            PassengerAccount.PayType.PAYTYPE_BALANCE,
                            order.getId(), order.getOrderNo(), 3, null,
                            true, true);
                    }
                    if (result.isSuccess()) {
                        // map.put("message", "支付成功");
                        // map.put("success", true);
                        map = this.payed(id, new BigDecimal(payed));
                    } else {
                        map.put("message", result.getMessage());
                        map.put("success", false);
                        map.put("code", -1);
                    }
                }
            }
        }
        return map;
    }

    @RequestMapping(value = "selectRentOrder", method = RequestMethod.GET)
    public RentOrder selectRentOrder(@RequestParam("id") Long id) {
        StringBuilder builder = new StringBuilder();
        builder.append(rentApi.getApiBaseURL())
            .append(RentApi.SELECT_RENTORDER).append("?appkey={appkey}");
        Map<String, String> kv = new HashMap<String, String>();
        if (id != null) {
            kv.put("id", id + "");
            builder.append("&id={id}");
        }
        String result = rentApi.get(builder.toString(), kv, settingUtils.get());

        if (null != result) {
            JSONObject jo = new JSONObject(result);
            Integer code = jo.getInt("code");
            if (code == 0) {
                JSONObject data = jo.getJSONObject("data");
                Gson gson = new GsonBuilder().create();
                RentOrder rentorder = gson.fromJson(data.toString(),
                    RentOrder.class);
                return rentorder;
            }
        }
        return null;
    }

    public Map<String, Object> payed(Long id, BigDecimal payed) {
        Map<String, Object> map = new HashMap<String, Object>();
        MultiValueMap<String, String> kv = new LinkedMultiValueMap<String, String>();
        kv.add("id", String.valueOf(id));
        kv.add("payed", String.valueOf(payed));
        String result = rentApi.postMultiValueMap(rentApi.getApiBaseURL()
            + RentApi.PAYED_RENTORDER, kv, settingUtils.get());
        JSONObject jo = new JSONObject(result);
        Integer code = jo.getInt("code");
        if (code == 0) {
            map.put("message", "支付成功");
            map.put("success", true);
            map.put("code", 0);
        } else {
            map.put("message", jo.getString("message"));
            map.put("success", false);
            map.put("code", -1);
        }
        return map;
    }
}
